package cn.xd.core.ddd.db;

import cn.xd.core.ddd.diff.EntityDiff;
import cn.xd.core.ddd.entity.Entity;
import cn.xd.core.ddd.value.IdValue;
import cn.xd.core.utils.DiffUtils;
import cn.xd.core.utils.SnapshotUtils;
import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

/**
 * @author : mirzaLin
 * @data : 2023/11/19
 * @description : db
 **/
public class DbContext<T extends Entity<ID>, ID extends IdValue> {

    @Getter
    private  Class<? extends T> aggregateClass;

    private final Map<IdValue, T> aggregateMap = new HashMap<>();

    public DbContext(Class<T> aggregateClass) {
        this.aggregateClass = aggregateClass;
    }

    public void attach(T aggregate) {
        if (aggregate.getId() != null) {
            this.merge(aggregate);
        }
    }

    public void detach(T aggregate) {
        if (aggregate.getId() != null) {
            aggregateMap.remove(aggregate.getId());
        }
    }

    public void detach(IdValue idValue) {
        if (idValue != null) {
            aggregateMap.remove(idValue);
        }
    }

    /**
     * 检查修改
     * @param aggregate
     * @return
     */
    public EntityDiff detectChanges(T aggregate) {
        if (aggregate.getId() == null) {
            return null;
        }
        T snapshot = aggregateMap.get(aggregate.getId());
        if (snapshot == null) {
            attach(aggregate);
        }
        return DiffUtils.diff(aggregate, snapshot, aggregateClass);
    }

    public T find(IdValue id) {
        return aggregateMap.get(id);
    }

    /**
     * 合并
     * @param aggregate
     */
    public void merge(T aggregate) {
        if (aggregate.getId() != null) {
            T snapshot = SnapshotUtils.snapshot(aggregate);
            IdValue id = aggregate.getId();
            aggregateMap.put(aggregate.getId(), snapshot);
        }
    }
}
